package com.wordpress.hybrid.util;

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;

public class FileOperations {
    private static final String TAG = FileOperations.class.getCanonicalName();

    public static boolean copyFile(InputStream inputStream, OutputStream outputStream) {
        final int BUFFER_SIZE = 1024 * 16;
        byte[] buffer = new byte[BUFFER_SIZE];
        int byteread = 0;
        try {
            while ((byteread = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, byteread);
            }
            outputStream.flush();
            return true;
        } catch (IOException e) {
            Log.e(TAG, e.toString());
        }

        return false;
    }

    public static boolean copyFile(Context context, Uri from, Uri to) {
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            inputStream = context.getContentResolver().openInputStream(from);
            outputStream = context.getContentResolver().openOutputStream(to);
            return copyFile(inputStream, outputStream);
        } catch (IOException e) {

        } finally {
            StreamHelper.closeSafe(inputStream);
            StreamHelper.closeSafe(outputStream);
        }

        return false;
    }

    public static boolean copyFile(String oldPath, String newPath) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        boolean ret = false;
        if (oldPath.equals(newPath)) {
            return ret;
        }
        try {
            final File newFile = new File(newPath);
            final File parent = newFile.getParentFile();
            if (parent != null && (parent.exists() || parent.mkdirs())) {
                final File oldfile = new File(oldPath);
                if (oldfile.exists()) { // 文件存在时
                    inputStream = new BufferedInputStream(new FileInputStream(oldfile)); // 读入原文件
                    outputStream = new BufferedOutputStream(new FileOutputStream(newFile));
                    copyFile(inputStream, outputStream);
                    ret = true;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                Log.e(TAG, e.toString());
            }
        }
        return ret;
    }

    public static String[] getSortedFileNameArr(String dirPath) {
        File dir = new File(dirPath);
        String[] names = dir.list();
        if (names != null) {
            Arrays.sort(names);
        }

        return names;
    }

    public static String[] getSortedFilePathArr(ArrayList<String> dirPaths) {
        final ArrayList<String> filePaths = new ArrayList<String>();
        for(String dirPath : dirPaths) {
            File dir = new File(dirPath);
            if (dir.isDirectory()) {
                final File[] files = dir.listFiles();

                if (files != null) {
                    for (File file : files) {
                        filePaths.add(file.getAbsolutePath());
                    }
                }
            }
        }
        if (filePaths.isEmpty()) {
            return null;
        }

        final String[] paths = new String[filePaths.size()];
        filePaths.toArray(paths);

        Arrays.sort(paths);
        return paths;
    }

    public static File getAbsoluteFile(File root, String path) {
        return new File(root.getAbsolutePath() + "/" + path);
    }

    public static boolean ensureParentExists(File file) {
        File parent = file.getParentFile();
        if (parent.exists()) {
            if (parent.isDirectory()) {
                return true;
            }
            parent.delete();
        }
        // we will not attempt to create the first directory in the path
        // (for example, do not create /sdcard if the SD card is not mounted)
        int secondSlash = file.getAbsolutePath().indexOf('/', 1);
        if (secondSlash < 1) return false;
        String directoryPath = file.getAbsolutePath().substring(0, secondSlash);
        File directory = new File(directoryPath);
        if (!directory.exists())
            return false;
        return parent.mkdirs();
    }

    public static boolean ensureFileExists(File file) {
        File parent = file.getParentFile();
        if (parent == null) {
            return false;
        }

        if (!ensureParentExists(file)) {
            return false;
        }

        try {
            return file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }

    public static boolean ensureDirExists(File dir) {
        if (dir.exists()) {
            if (dir.isDirectory()) {
                return true;
            }
            dir.delete();
        }
        // we will not attempt to create the first directory in the path
        // (for example, do not create /sdcard if the SD card is not mounted)
        int secondSlash = dir.getAbsolutePath().indexOf('/', 1);
        if (secondSlash < 1) return false;
        String directoryPath = dir.getAbsolutePath().substring(0, secondSlash);
        File directory = new File(directoryPath);
        if (!directory.exists())
            return false;
        return dir.mkdirs();
    }

    public static boolean saveToFile(File file, byte[] data) {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(file);
            os.write(data);
            os.flush();
            return true;
        } catch (FileNotFoundException e) {
            Log.e(TAG, e.toString());
        } catch (IOException e) {
            Log.e(TAG, e.toString());
        } finally {
            StreamHelper.closeSafe(os);
        }

        return false;
    }

    public static void writeUTF8StringToFile(File file, String str) throws IOException {
        FileOutputStream fos = new FileOutputStream(file);
        try {
            fos.write(str.getBytes("utf-8"));
        } finally {
            StreamHelper.closeSafe(fos);
        }
    }

    public static String readUTF8StringFromFile(File file) throws IOException {
        byte[] buffer = new byte[4096];
        FileInputStream fin = null;
        ByteArrayOutputStream bos = null;
        try {
            int i = 0;
            fin = new FileInputStream(file);
            bos = new ByteArrayOutputStream();
            while ((i = fin.read(buffer, 0, buffer.length)) != -1) {
                bos.write(buffer, 0, i);
            }
            return new String(bos.toByteArray(), "utf-8");
        } finally {
            StreamHelper.closeSafe(fin);
            StreamHelper.closeSafe(bos);
        }
    }

    public static void deleteRecrusively(File file) {
        if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null) {
                for (File f : children) {
                    deleteRecrusively(f);
                }
            }
        }

        file.delete();
    }
}
